package top.haijunit.common.redis.config;

import org.aopalliance.aop.Advice;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.haijunit.common.redis.RedissonService;
import top.haijunit.common.redis.annotation.RedissonLock;
import top.haijunit.common.redis.interceptor.RedissonLockInterceptor;

/**
 * redisson自动配置类
 *
 * @author zhanghaijun
 * @since 2024-07-31
 */
@Configuration
@ConditionalOnClass(RedissonClient.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {

    @Bean
    public RedissonService redissonService(RedissonProperties redissonProperties) {
        return new RedissonService(redissonClient(redissonProperties));
    }

    @Bean
    @ConditionalOnMissingBean(RedissonClient.class)
    public RedissonClient redissonClient(RedissonProperties redissonProperties) {
        Config config = new Config();
        config.setCodec(new JsonJacksonCodec());
        config.useSingleServer()
                .setAddress(redissonProperties.getAddress())
                .setDatabase(redissonProperties.getDatabase())
                .setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize())
                .setConnectionPoolSize(redissonProperties.getConnectionPoolSize())
                .setDnsMonitoringInterval(redissonProperties.getDnsMonitoringInterval())
                .setConnectTimeout(redissonProperties.getConnectTimeout())
                .setTimeout(redissonProperties.getTimeout())
                .setPassword(redissonProperties.getPassword())
                .setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout())
                .setRetryAttempts(redissonProperties.getRetryAttempts())
                .setRetryInterval(redissonProperties.getRetryInterval());
        return Redisson.create(config);
    }

    @Bean
    public Advisor redissonLockAdvisor(RedissonService redissonService) {
        Pointcut pointcut = AnnotationMatchingPointcut.forMethodAnnotation(RedissonLock.class);
        Advice advice = new RedissonLockInterceptor(redissonService);
        return new DefaultPointcutAdvisor(pointcut, advice);
    }
}
